/*
Date: Sun 10 Nov 2013

This application test to automatically load the bytecode and bytedata to the rovex

*/


#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> //open
#include <unistd.h> //close 
#include <byteswap.h>
#include <unistd.h>


#define RVEX_CTRL_RESET  '2'
#define RVEX_CTRL_START '1'

#define RVEX_STAT_BUSY '3' // task is being executed
#define RVEX_STAT_IDLE '1' //task is not running or task has just finished
#define RVEX_STAT_DONE '0' //task finishes execution 

#define RVEX_DMEM_DIR "/dev/rvex-dmemory.0" //rvex data memory
#define RVEX_IMEM_DIR "/dev/rvex-imemory.0"  //rvex instruction memory 
#define RVEX_CTRL_DIR "/sys/devices/virtual/rvex_core/rvex-smemory.0/rvex_core_ctl"   //rvex control register
#define RVEX_STATUS_DIR "/sys/devices/virtual/rvex_core/rvex-smemory.0/rvex_core_status" //rvex status register

#define DATA_SIZE 32
#define DATA_SIZE_READ 80

/*bytecode and bytedata for kernel1 */
#define BYTECODE_DIR "bytecode" //directory for function1 bytecode 
#define BYTEDATA_DIR "bytedata"  //directory for function1 bytedata 


/*bytecode and bytedata for kernel2 */
#define BYTECODE2_DIR "bytecode2" //directory for function1 bytecode 
#define BYTEDATA2_DIR "bytedata2"  //directory for function1 bytedata 

/*
int data_package [8]; //data buffer to send to rvex dmem
int data_package_read [8]; //data buffer to read rvex dmem
*/


char data_package [DATA_SIZE]; //data buffer to send to rvex dmem
char data_package2 [DATA_SIZE]; //data buffer to send to rvex dmem
int i_data_package3;
//char data_package_read [DATA_SIZE]; //data buffer to read rvex dmem
char data_package_read [DATA_SIZE_READ]; //data buffer to read rvex dmem
//char data_package_read2 [16]; //data buffer to read rvex dmem
//char data_package_read3 [400]; //data buffer to read rvex dmem


/* functon running on rovex*/
//int add(int a, int b);
int add(char a, char b);
int sub(char a, char b);



int main(int argc, char** argv ) 
{
	char r=5;
	char d=3;
	 
	int results;

	int i; 
	int num_buf_elements;
	
	printf("\n\nRunning MicroBlaze App\n "); 
	
	
	/*call function1 */
	printf("Kernel1 call.....\n"); 
	results=add(r,d); 	
	printf("Kernel1 finish\n"); 

	printf("%d + %d =%d\n ",r,d,results); 


	printf("Kernel2 call.....\n"); 
	results=sub(r,d); 	
	printf("Kernel2 finish\n"); 

	printf("%d - %d =%d\n ",r,d,results); 



	for(i=0; i<sizeof(data_package_read); i++)
 	     printf(" data_package[%d]:%d\n",i,  data_package_read[i]);


return 0;


}//end main function





int add(char a, char b) 
{
 	/* File discriptors of the hardware for the system calls */ 
  	int fd_rv_ctrl_reg = open(RVEX_CTRL_DIR,O_WRONLY);  	// open the control register for write only
  	int fd_rv_status_reg = open(RVEX_STATUS_DIR,O_RDONLY); 	// open the status  register for read only 
 	//int fd_rv_dmem_reg = open(RVEX_DMEM_DIR,O_RDWR);  	// open the data memory for read and write

	int fd_bytecode; 	//pointer to function1 bytecode 
	char *buffer_bytecode;	//buffer to store bytecode  
	int length_bytecode;  	//size of bytecode 
	struct stat info_bytecode; //general information about bytecode
	
	int fd_bytedata; 	//pointer to function1 bytedata 
	char *buffer_bytedata;  //buffer to store bytedata
	int length_bytedata;   //size of bytedata 
	struct stat info_bytedata;  //general information about  bytedata 
	
	int fd_rvex_imem; //pointer to rvex imem 
	int fd_rvex_dmem; //pointer to rvex dmem
	char f[2]; 
  
  	int check_stat; //checks system calls 
  	char command; //commands to echo to the rovex control register  
 	// int timer=0; //timeout for reading rvex datamemory
  	int i;
   	int data_size; 		//size in bytes of data to send to rovex
   	int data_type_size; 	//size of data type of the data to send to rovex 
   	int data_num_elements; 	//number of elements in data package to rovex
  
	off_t fd_current_position;  //get position of file discriptor
	int offset_bytes; //ofset for filediscriptor in bytes
	int return_value; //value to return in function call, for x264


	//int char_count; //monitor when char reaches max count, 256
	char counter=0;




//-------------------------------------------------------------------------------
//    Fetch and store bytecode and bytedata in rvex Imem and Dmem respectively 
//-------------------------------------------------------------------------------


	 /*open bytecode for read*/
        fd_bytecode = open(BYTECODE_DIR, O_RDONLY);
        if(fd_bytecode==-1)
        {
                 printf("error opening bytecode1\n");
                exit(0);
        }
//	printf("bytecode1 opened\n"); 


	 /*open bytedata for read*/
        fd_bytedata = open(BYTEDATA_DIR, O_RDONLY);
        if(fd_bytedata==-1)
        {
                 printf("error opening bytedata1\n");
                exit(0);
        }
//	printf("bytedata1 opened\n"); 


	 /*open rvex IMEM for  write*/
        fd_rvex_imem = open( RVEX_IMEM_DIR,O_WRONLY ); 
        if(fd_rvex_imem ==-1)
        {
                 printf("error opening rvex IMEM\n");
                exit(0);
        }
//	printf("rvex IMEM opened\n"); 

	
	 /*open rvex DMEM for read and write*/
        fd_rvex_dmem = open( RVEX_DMEM_DIR, O_RDWR); 
        if(fd_rvex_dmem ==-1)
        {
                 printf("error opening rvex DMEM\n");
                exit(0);
        }
//	printf("rvex DMEM opened\n"); 


          /*get information of bytecode*/
          fstat(fd_bytecode,&info_bytecode);
         length_bytecode= info_bytecode.st_size;
 
         /*get information of bytedata*/
         fstat(fd_bytedata,&info_bytedata);
         length_bytedata= info_bytedata.st_size;
 
         /*allocate buffer to hold the contents of bytecod and bytedata */
         buffer_bytecode = (char*) malloc (length_bytecode);
         buffer_bytedata = (char*) malloc (length_bytedata);

	  /*read bytecodes and bytedata into buffer */
 	 check_stat= read(fd_bytecode,buffer_bytecode,length_bytecode);
         
 	if(check_stat == -1)
  	{ 
   		printf("bytecode read failed\n");
   		exit(0);  
  	}    
  //	else printf("bytecode read Success\n");


	check_stat= read(fd_bytedata,buffer_bytedata,length_bytedata);

 	if(check_stat == -1)
  	{ 
   		printf("bytedata read failed\n");
   		exit(0);  
  	}    
  //	else printf("bytedata read Success\n");


	  /*load bytecode in IMEM */
  check_stat=  write(fd_rvex_imem,buffer_bytecode, length_bytecode);

 	if(check_stat == -1)
  	{ 
   		printf("Imem Write failed\n");
   		exit(0);  
  	}    
  //	else printf("Imem Write Success\n");



	  /*load bytedata in DMEM */
         write(fd_rvex_dmem,buffer_bytedata, length_bytedata);

 	if(check_stat == -1)
  	{ 
   		printf("Dmem Write failed\n");
   		exit(0);  
  	}    
  //	else printf("Dmem Write Success\n"); 


	printf("finish loading bytecode and bytedata\n\n"); 

//-------------------------------------------------------------------------------
//    SEND Parameters to DMEM  //0x120 - 0x121 
//-------------------------------------------------------------------------------

	/* set cursor at correct dmem location using fd  */
	
	//offset_bytes=4;
	offset_bytes=0;
	fd_current_position= lseek (fd_rvex_dmem,offset_bytes,SEEK_SET); //set cursor offset_byte further from file beginning   //address at 0x120 in Dmem


          offset_bytes=0;
         fd_current_position= lseek (fd_rvex_dmem,offset_bytes,SEEK_CUR); //find curent cursor to confirm
    //     printf("current position in file  write: %ld \n", fd_current_position );
 



	/* send parameters to rvex */

  //	printf("\nRvex Dmem write ...\n"); 

        //a=100;
   	f[0]=a; 
	f[1]=b;
 

//	printf("Sending Parameter 1....\n");	
//	printf("Writing %ld bytes \n ", sizeof(f));  
  	check_stat= write(fd_rvex_dmem,f,sizeof(f)); //0x120 


  	
	if(check_stat == -1)
  	{ 
   		printf("Dmem Write Failed\n");
   		exit(0);  
  	}    
  //	else  printf("Write Success\n");


//-------------------------------------------------------------------------------
//    START ROVEX 
//-------------------------------------------------------------------------------
  	/* reset rvex */
  	command='2';
  //	printf("\n\nrvex reset...\n"); 
  	check_stat= write(fd_rv_ctrl_reg,&command,1);

 	if(check_stat == -1)
  	{ 
   		printf("Reset Failed\n");
   		exit(0);  
  	}    
  //	else printf("Reset Success\n");

  	/* start rvex */
  	command='1';
  	//write(fd_rv_ctrl_reg,&command,sizeof(command));
  //	printf("\n\nStart rvex\n"); 
  	check_stat= write(fd_rv_ctrl_reg,&command,1);   
 
  	if(check_stat == -1)
  	{ 
   		printf("Start Failed\n");
   		exit(0);  
  	}    
  //	else  printf("Start Success\n\n");




//-------------------------------------------------------------------------------
//    Wait until rovex finish 
//-------------------------------------------------------------------------------

  	/* wait until rvex finish */
  	command='0';
  //	printf("Wait until rvex finish .....\n"); 
  	while(command != '3'){ 
		/*check if rovex is finish */
   		check_stat= read(fd_rv_status_reg,&command,1); //read status until rvex control bit is 0b011=>done
	} 
  	printf("rvex done\n"); 



//-------------------------------------------------------------------------------
//    Read Results in Dmem 
//-------------------------------------------------------------------------------
	
	
	
	lseek(fd_rvex_dmem,0, SEEK_SET); //set cursor at beginning.
	check_stat= read(fd_rvex_dmem, &return_value,sizeof(return_value)); 
  
	if(check_stat == -1)
  	{ 
   		printf("Read Failed\n");
   		exit(0);  
  	}    
  	else  printf("Read Success\n");

	printf("Read integer value,byteswap :%d\n ", bswap_32(return_value) ); 


 /* Read 400 bytes from start from Data memory */
         printf("\nRead Trial #3\n " );
         offset_bytes=0;
         fd_current_position= lseek (fd_rvex_dmem,offset_bytes,SEEK_CUR); //find curent cursor
    //     printf("\ncurrent position in file after everythig %ld \n", fd_current_position );

//	printf("readig %d bytes for data package \n", sizeof(data_package_read)); 
         lseek(fd_rvex_dmem,0, SEEK_SET); //set cursor at beginning.
         check_stat= read(fd_rvex_dmem, data_package_read, sizeof(data_package_read)); //read status until rvex control bit is 0b011    =>done









	/*close all FD and dynamic memory */
	free (buffer_bytecode);
	free (buffer_bytedata );
  	close(fd_rv_ctrl_reg); 
  	close(fd_rv_status_reg); 
 	close(fd_rvex_dmem);
 	close(fd_rvex_imem);
 	close(fd_bytecode);
 	close(fd_bytedata);


	/*return results to caller*/
	return (bswap_32(return_value) ) ;

}


//---------------------------------------------------------------------------------------
//----------------  KERNEL 2------------------------------------------------------------
//-------------------------------------------------------------------------------------

int sub(char a, char b) 
{
 	/* File discriptors of the hardware for the system calls */ 
  	int fd_rv_ctrl_reg = open(RVEX_CTRL_DIR,O_WRONLY);  	// open the control register for write only
  	int fd_rv_status_reg = open(RVEX_STATUS_DIR,O_RDONLY); 	// open the status  register for read only 
 	//int fd_rv_dmem_reg = open(RVEX_DMEM_DIR,O_RDWR);  	// open the data memory for read and write

	int fd_bytecode; 	//pointer to function1 bytecode 
	char *buffer_bytecode;	//buffer to store bytecode  
	int length_bytecode;  	//size of bytecode 
	struct stat info_bytecode; //general information about bytecode
	
	int fd_bytedata; 	//pointer to function1 bytedata 
	char *buffer_bytedata;  //buffer to store bytedata
	int length_bytedata;   //size of bytedata 
	struct stat info_bytedata;  //general information about  bytedata 
	
	int fd_rvex_imem; //pointer to rvex imem 
	int fd_rvex_dmem; //pointer to rvex dmem
	char f[2]; 
  
  	int check_stat; //checks system calls 
  	char command; //commands to echo to the rovex control register  
 	// int timer=0; //timeout for reading rvex datamemory
  	int i;
   	int data_size; 		//size in bytes of data to send to rovex
   	int data_type_size; 	//size of data type of the data to send to rovex 
   	int data_num_elements; 	//number of elements in data package to rovex
  
	off_t fd_current_position;  //get position of file discriptor
	int offset_bytes; //ofset for filediscriptor in bytes
	int return_value; //value to return in function call, for x264


	//int char_count; //monitor when char reaches max count, 256
	char counter=0;




//-------------------------------------------------------------------------------
//    Fetch and store bytecode and bytedata in rvex Imem and Dmem respectively 
//-------------------------------------------------------------------------------


	 /*open bytecode for read*/
        fd_bytecode = open(BYTECODE2_DIR, O_RDONLY);
        if(fd_bytecode==-1)
        {
                 printf("error opening bytecode1\n");
                exit(0);
        }
//	printf("bytecode1 opened\n"); 


	 /*open bytedata for read*/
        fd_bytedata = open(BYTEDATA2_DIR, O_RDONLY);
        if(fd_bytedata==-1)
        {
                 printf("error opening bytedata1\n");
                exit(0);
        }
//	printf("bytedata1 opened\n"); 


	 /*open rvex IMEM for  write*/
        fd_rvex_imem = open( RVEX_IMEM_DIR,O_WRONLY ); 
        if(fd_rvex_imem ==-1)
        {
                 printf("error opening rvex IMEM\n");
                exit(0);
        }
//	printf("rvex IMEM opened\n"); 

	
	 /*open rvex DMEM for read and write*/
        fd_rvex_dmem = open( RVEX_DMEM_DIR, O_RDWR); 
        if(fd_rvex_dmem ==-1)
        {
                 printf("error opening rvex DMEM\n");
                exit(0);
        }
//	printf("rvex DMEM opened\n"); 


          /*get information of bytecode*/
          fstat(fd_bytecode,&info_bytecode);
         length_bytecode= info_bytecode.st_size;
 
         /*get information of bytedata*/
         fstat(fd_bytedata,&info_bytedata);
         length_bytedata= info_bytedata.st_size;
 
         /*allocate buffer to hold the contents of bytecod and bytedata */
         buffer_bytecode = (char*) malloc (length_bytecode);
         buffer_bytedata = (char*) malloc (length_bytedata);

	  /*read bytecodes and bytedata into buffer */
 	 check_stat= read(fd_bytecode,buffer_bytecode,length_bytecode);
         
 	if(check_stat == -1)
  	{ 
   		printf("bytecode read failed\n");
   		exit(0);  
  	}    
  //	else printf("bytecode read Success\n");


	check_stat= read(fd_bytedata,buffer_bytedata,length_bytedata);

 	if(check_stat == -1)
  	{ 
   		printf("bytedata read failed\n");
   		exit(0);  
  	}    
  //	else printf("bytedata read Success\n");


	  /*load bytecode in IMEM */
  check_stat=  write(fd_rvex_imem,buffer_bytecode, length_bytecode);

 	if(check_stat == -1)
  	{ 
   		printf("Imem Write failed\n");
   		exit(0);  
  	}    
  //	else printf("Imem Write Success\n");



	  /*load bytedata in DMEM */
         write(fd_rvex_dmem,buffer_bytedata, length_bytedata);

 	if(check_stat == -1)
  	{ 
   		printf("Dmem Write failed\n");
   		exit(0);  
  	}    
  //	else printf("Dmem Write Success\n"); 


	printf("finish loading bytecode and bytedata\n\n"); 

//-------------------------------------------------------------------------------
//    SEND Parameters to DMEM  //0x120 - 0x121 
//-------------------------------------------------------------------------------

	/* set cursor at correct dmem location using fd  */
	
	//offset_bytes=4;
	offset_bytes=0;
	fd_current_position= lseek (fd_rvex_dmem,offset_bytes,SEEK_SET); //set cursor offset_byte further from file beginning   //address at 0x120 in Dmem


          offset_bytes=0;
         fd_current_position= lseek (fd_rvex_dmem,offset_bytes,SEEK_CUR); //find curent cursor to confirm
    //     printf("current position in file  write: %ld \n", fd_current_position );
 



	/* send parameters to rvex */

  //	printf("\nRvex Dmem write ...\n"); 

        //a=100;
   	f[0]=a; 
	f[1]=b;
 
/*	printf("Sending Parameter 1....\n");	
	printf("Writing %ld bytes \n ", sizeof(a));  
	printf("value to be written: %d \n ", a);  
  	check_stat= write(fd_rvex_dmem,&a,sizeof(a)); //0x120 
  */


//	printf("Sending Parameter 1....\n");	
//	printf("Writing %ld bytes \n ", sizeof(f));  
  	check_stat= write(fd_rvex_dmem,f,sizeof(f)); //0x120 


  	
	if(check_stat == -1)
  	{ 
   		printf("Dmem Write Failed\n");
   		exit(0);  
  	}    
  //	else  printf("Write Success\n");


//-------------------------------------------------------------------------------
//    START ROVEX 
//-------------------------------------------------------------------------------
  	/* reset rvex */
  	command='2';
  //	printf("\n\nrvex reset...\n"); 
  	check_stat= write(fd_rv_ctrl_reg,&command,1);

 	if(check_stat == -1)
  	{ 
   		printf("Reset Failed\n");
   		exit(0);  
  	}    
  //	else printf("Reset Success\n");

  	/* start rvex */
  	command='1';
  	//write(fd_rv_ctrl_reg,&command,sizeof(command));
  //	printf("\n\nStart rvex\n"); 
  	check_stat= write(fd_rv_ctrl_reg,&command,1);   
 
  	if(check_stat == -1)
  	{ 
   		printf("Start Failed\n");
   		exit(0);  
  	}    
  //	else  printf("Start Success\n\n");




//-------------------------------------------------------------------------------
//    Wait until rovex finish 
//-------------------------------------------------------------------------------

  	/* wait until rvex finish */
  	command='0';
  	printf("Wait until rvex finish .....\n"); 
  	while(command != '3'){ 
		/*check if rovex is finish */
   		check_stat= read(fd_rv_status_reg,&command,1); //read status until rvex control bit is 0b011=>done
	} 
  	printf("rvex done\n"); 



//-------------------------------------------------------------------------------
//    Read Results in Dmem 
//-------------------------------------------------------------------------------
	
	
	
	lseek(fd_rvex_dmem,0, SEEK_SET); //set cursor at beginning.
	check_stat= read(fd_rvex_dmem, &return_value,sizeof(return_value)); 
  
	if(check_stat == -1)
  	{ 
   		printf("Read Failed\n");
   		exit(0);  
  	}    
  //	else  printf("Read Success\n");

	printf("Read integer value,byteswap :%d\n ", bswap_32(return_value) ); 


 /* Read 400 bytes from start from Data memory */
         printf("\nRead Trial #3\n " );
         offset_bytes=0;
         fd_current_position= lseek (fd_rvex_dmem,offset_bytes,SEEK_CUR); //find curent cursor
    //     printf("\ncurrent position in file after everythig %ld \n", fd_current_position );

//	printf("readig %d bytes for data package \n", sizeof(data_package_read)); 
         lseek(fd_rvex_dmem,0, SEEK_SET); //set cursor at beginning.
         check_stat= read(fd_rvex_dmem, data_package_read, sizeof(data_package_read)); //read status until rvex control bit is 0b011    =>done









	/*close all FD and dynamic memory */
	free (buffer_bytecode);
	free (buffer_bytedata );
  	close(fd_rv_ctrl_reg); 
  	close(fd_rv_status_reg); 
 	close(fd_rvex_dmem);
 	close(fd_rvex_imem);
 	close(fd_bytecode);
 	close(fd_bytedata);


	/*return results to caller*/
	return (bswap_32(return_value) ) ;

}


